package com.zy.explore.search.application.service;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.zy.explore.search.interfaces.frm.ProductSolrFrm;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 建类说明：solr服务
 *
 * @author 中国印
 * @date 2022年02月10日 00:42:10
 */
@Service
public class SolrService {

    private final String db_core = "test_core";
    private final String file_core = "file_core";
    private final String fileDataImport = file_core + "/dataimport?command=full-import&clean=false&commit=true&entity=file";

    @Value("${spring.data.solr.host}")
    private String solrHost;

    @Resource
    private SolrClient client;

    /**
     * 高亮查询
     */
    public SolrDocumentList querySolr(String collection, String q, String field) throws IOException, SolrServerException {
        SolrQuery params = new SolrQuery();
        //查询条件, 这里的 q 对应 下面图片标红的地方
        params.set("q", q);
        //过滤条件
        // params.set("fq", "product_price:[100 TO 100000]");
        //排序
        // params.addSort("id", SolrQuery.ORDER.asc);
        //分页
        params.setStart(0);
        params.setRows(20);
        //默认域
        params.set("df", field);
        //只查询指定域
        // params.set("fl", content + ",content,id,title,author");
        //高亮
        //打开开关
        params.setHighlight(true);
        //指定高亮域
        params.addHighlightField("id");
        params.addHighlightField(field);
        params.addHighlightField("title");
        params.addHighlightField("content");
        params.addHighlightField("author");

        params.addHighlightField("productName");
        params.addHighlightField("productDesc");

        //设置前缀
        params.setHighlightSimplePre("<span style='color:red'>");
        //设置后缀
        params.setHighlightSimplePost("</span>");

        QueryResponse queryResponse = client.query(collection, params);

        SolrDocumentList results = queryResponse.getResults();

        // 查询到的结果
        long numFound = results.getNumFound();

        //获取高亮显示的结果, 高亮显示的结果和查询结果是分开放的
        Map<String, Map<String, List<String>>> highlight = queryResponse.getHighlighting();

        // 将高亮结果合并到查询结果中
        for (SolrDocument result : results) {
            result.remove("keyword");
            highlight.forEach((k, v) -> {
                if (result.get("id").equals(k)) {
                    v.forEach((k1, v1) -> {
                        if (!k1.equals("keyword")) {
                            // 高亮列合并如结果
                            result.setField(k1, v1);
                        }
                    });
                }
            });
        }
        return results;
    }

    /**
     * 根据ID查询
     */
    public SolrDocument getById(String collection, String id) throws IOException, SolrServerException {
        return client.getById(id);
    }

    /**
     * 删除全部索引
     *
     * @param collection
     */
    public boolean deleteAll(String collection) {
        if (StringUtils.isEmpty(collection)) {
            collection = db_core;
        }
        try {
            client.deleteByQuery(collection, "*:*");
            client.commit(collection);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public String save(ProductSolrFrm frm) {
        String id = frm.getId();
        if (StringUtils.isEmpty(id)) {
            id = UUID.randomUUID().toString().replaceAll("-", "");
        }
        try {
            client.addBean(db_core, frm);
            return id;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public boolean deleteById(String id) {
        try {
            client.deleteById(db_core, id);
            client.commit(db_core);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public String findById(String id) {
        SolrDocument document = null;
        try {
            document = client.getById(db_core, id);
        } catch (SolrServerException | IOException e) {
            e.printStackTrace();
        }
        if (document != null) {
            return document.toString();
        }
        return null;
    }

    public <T>T findById(String id, Class<T> returnClass) {
        SolrDocument document = null;
        try {
            document = client.getById(db_core, id);
        } catch (SolrServerException | IOException e) {
            e.printStackTrace();
        }
        if (document == null) {
            return null;
        }
        Collection<String> fieldNames = document.getFieldNames();
        System.out.println(fieldNames);

        // SolrDocument{id=783ad2cf772f4e32a12f8b335ff7ee4f-d, type=d, titleProper=检索测试3, ... _version_=1724357965132070912}
        String documentStr = document.toString();
        String[] kvs = documentStr.substring(13, documentStr.lastIndexOf("}")).replace(" ", "").split(",");
        if (kvs.length > 0) {
            Map<String, String> map = Maps.newHashMap();
            for (String kv : kvs) {
                String[] keyValue = kv.split("=");
                map.put(keyValue[0], keyValue[1]);
            }
            return JSON.parseObject(JSON.toJSONString(map), returnClass);
        }

        return null;
    }

    public SolrDocumentList search(String q) {
        SolrDocumentList results = null;
        try {
            results = querySolr(db_core, "*" + q + "*", "field1");
        } catch (IOException | SolrServerException e) {
            e.printStackTrace();
        }
        return results;
    }

    public boolean dataImport() {
        // 1、清空索引，生产环境不建议这样使用，可以保存文件新建及更新时间，增量创建索引
        deleteAll(file_core);

        // 2、创建索引
        Mono<String> result = WebClient.create(solrHost)
                .get()
                .uri(fileDataImport)
                .retrieve()
                .bodyToMono(String.class);
        result.block();
        return true;
    }

    public SolrDocumentList searchDoc(String q) {
        SolrDocumentList result = null;
        try {
            result = querySolr(file_core, "*" + q + "*", "keyword");
        } catch (IOException | SolrServerException e) {
            e.printStackTrace();
        }
        return result;
    }
}
